iT邦幫忙

2023 iThome 鐵人賽

DAY 5
0
自我挑戰組

JS 加強筆記系列 第 5

Day 05:then、catch、finally

  • 分享至 

  • xImage
  •  

前面寫到 producing code 完成了工作,並呼叫 resolvereject 送出結果,接下來 consuming code 可以利用 promise 的 thencatchfinally 等方法進行後續。

then

語法:

promise.then(
    function(result) { /* 處理成功的結果 */ },
    function(error) { /* 處理錯誤 */ }
);

then 可以傳入兩個 callback 參數,第一個會在 promise 狀態變為 fulfilled 時執行並接收結果;第二個 (非必要) 則是 rejected 時執行接收錯誤。

// fulfilled 的情況
let promise = new Promise(function(resolve, reject) {
    setTimeout(() => resolve('done!'), 1000);
});

// 執行第一個 callback
promise.then(
    result => alert(result), // 一秒後顯示 'done!'
    error => alert(error) // 不執行
);
// rejected 的情況
let promise = new Promise(function(resolve, reject) {
    setTimeout(() => reject(new Error('Whoops!')), 1000);
});

// 執行第二個 callback
promise.then(
    result => alert(result), // 不執行
    error => alert(error) // 一秒後顯示 'Error: Whoops!'
);

如果 then 只處理成功情況可以只寫第一個參數,只處理錯誤可以第一個參數寫成 null,如 .then(null, errorHandlingFunction) 或者採用下方 catch 的寫法。

catch

使用 catch(f) 跟上述的 .then(null, f) 是一樣的意思:

let promise = new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error('Whoops!')), 1000);
});

promise.catch(alert); // 一秒後顯示 'Error: Whoops!'

善後:finally

finally 方法同樣是傳入 callback 函式,它和 then 相似的地方在於只要 promise 有結果 (settled),無論成功失敗,finally 中的函式都會執行。finally 的用意是做整個任務的最終總整理 (cleanup/ finalizing),例如停止 loading 狀態或中斷不用的連結。就像一個活動結束後,無論是失敗或成功都要清理善後。

new Promise((resolve, reject) => {
     setTimeout(() => resolve('value'), 2000);
})
    .finally(() => alert('Promise ready')) // 無論結果如何都先執行
    .then(result => alert(result)); // 'value'

從例子中可以看出 finally 的一些特性還有和 then 的差異:

  • finally 中的函式沒有參數。finally 不用來處理結果,也不知道 promise 成功與否,它只是做 promise 結束後都要做的事。
  • 例子中 finally 先執行,但後面的 then 仍然印出結果,也就是 promise 結果會直接「穿過」 finally 到後面對應的處理函式。也因此 finally 不一定要擺在最後呼叫。
  • finally 不應回傳東西,硬要回傳也會被忽略。例外是當它丟出錯誤或回傳一個 rejected promise 時,會將這個錯誤 (而非原本的結果) 傳給後面的錯誤處理函式。(嚴格來說例子中的箭頭函式就是有回傳,個人不喜歡這種寫法,但先保留。)

呼叫方法的時間點

promise 的狀態為 'pending' 時,thencatchfinally 方法會等待它的結果。

如果 promise 已經 settled,thencatchfinally 則會立刻執行,但並不影響結果。

let promise = new Promise(resolve => resolve('done!'));

promise.then(alert); // done!

這個例子中 executor 同步呼叫了 resolve,promise 在建立時就會立刻 settled,但並不影響後面才加上處理函式。換句話說,處理函式可以在任何時候加上,如果已經有結果就會馬上執行,這樣的特性也讓 promise 更有彈性。


上一篇
Day 04:promise 結構及特性
下一篇
Day 06:callback 函式初步改寫
系列文
JS 加強筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言